use crate::client::http::build_client;
use crate::types::{
    Result, SinaCffexSpot, SinaCffexContract, SinaCffexDaily,
    SseSpotPrice, SseGreeks, SseMinute, SseDaily, FinanceMinute,
    CommodityContract, CommodityContractTable, CommodityOptionHist,
};
use serde_json::Value;

/// 新浪财经-中金所-上证50指数期权合约列表
/// 
/// 获取上证50指数期权的所有可用合约代码
/// 目标地址: https://stock.finance.sina.com.cn/futures/view/optionsCffexDP.php
/// 
/// # 返回
/// - `Vec<String>`: 合约代码列表，例如 ["ho2511", "ho2512", "ho2603", ...]
/// 
/// # 示例
/// ```no_run
/// use akoption::option_cffex_sz50_list_sina;
/// 
/// #[tokio::main]
/// async fn main() -> anyhow::Result<()> {
///     let contracts = option_cffex_sz50_list_sina().await?;
///     println!("上证50期权合约: {:?}", contracts);
///     Ok(())
/// }

/// 新浪财经-金融期权-分时数据（完整字段）
/// 
/// 与 Python 版本一致，返回日期、时间、价格、均价、成交量
pub async fn option_finance_minute_full_sina(symbol: &str) -> Result<Vec<FinanceMinute>> {
    let url = "https://stock.finance.sina.com.cn/futures/api/openapi.php/StockOptionDaylineService.getFiveDayLine";
    let client = crate::client::http::build_client_with_headers(vec![
        ("Referer", "https://stock.finance.sina.com.cn/option/quotes.html"),
        ("Accept", "*/*"),
        ("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"),
        ("Cache-Control", "no-cache"),
        ("Pragma", "no-cache"),
        (
            "User-Agent",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
        ),
    ])?;

    let resp = client
        .get(url)
        .query(&[("symbol", format!("CON_OP_{}", symbol))])
        .send()
        .await?;
    let json: Value = resp.json().await?;

    let parse_num = |v: &Value| -> Option<f64> {
        v.as_f64().or_else(|| v.as_str().and_then(|s| {
            let s = s.trim();
            if s.is_empty() || s == "-" { None } else { s.parse::<f64>().ok() }
        }))
    };

    let mut out: Vec<FinanceMinute> = Vec::new();
    if let Some(days) = json.get("result").and_then(|v| v.get("data")).and_then(|v| v.as_array()) {
        for day in days {
            match day {
                Value::Array(rows) => {
                    let mut last_date: Option<String> = None;
                    for row in rows {
                        match row {
                            // 索引: [time, price, volume, _, average_price, date]
                            Value::Array(cols) => {
                                let time_str = cols.get(0).and_then(|v| v.as_str()).unwrap_or("").to_string();
                                if let Some(d) = cols.get(5).and_then(|v| v.as_str()) { if !d.is_empty() { last_date = Some(d.to_string()); } }
                                let date = last_date.clone().unwrap_or_default();
                                let price = cols.get(1).and_then(parse_num);
                                let volume = cols.get(2).and_then(parse_num);
                                let average_price = cols.get(4).and_then(parse_num);
                                out.push(FinanceMinute { date, time: time_str, price, average_price, volume });
                            }
                            // 对象: 键 time/price/volume/date/average_price 或 i/p/v/d/ap/avg
                            Value::Object(obj) => {
                                let time_str = obj.get("time").or_else(|| obj.get("i")).and_then(|v| v.as_str()).unwrap_or("").to_string();
                                if let Some(dv) = obj.get("date").or_else(|| obj.get("d")) { if let Some(d) = dv.as_str() { if !d.is_empty() { last_date = Some(d.to_string()); } } }
                                let date = last_date.clone().unwrap_or_default();
                                let price = obj.get("price").or_else(|| obj.get("p")).and_then(parse_num);
                                let volume = obj.get("volume").or_else(|| obj.get("v")).and_then(parse_num);
                                let average_price = obj.get("average_price")
                                    .or_else(|| obj.get("avg"))
                                    .or_else(|| obj.get("ap"))
                                    .and_then(parse_num);
                                out.push(FinanceMinute { date, time: time_str, price, average_price, volume });
                            }
                            _ => {}
                        }
                    }
                }
                _ => {}
            }
        }
    } else {
        return Err(anyhow::anyhow!("No JSON array in response"));
    }

    Ok(out)
}
/// ```
pub async fn option_cffex_sz50_list_sina() -> Result<Vec<String>> {
    fetch_cffex_list("ho").await
}

/// 新浪财经-中金所-沪深300指数期权合约列表
/// 
/// 获取沪深300指数期权的所有可用合约代码
pub async fn option_cffex_hs300_list_sina() -> Result<Vec<String>> {
    fetch_cffex_list("mo").await
}

/// 新浪财经-中金所-中证1000指数期权合约列表
/// 
/// 获取中证1000指数期权的所有可用合约代码
pub async fn option_cffex_zz1000_list_sina() -> Result<Vec<String>> {
    fetch_cffex_list("io").await
}

/// 新浪财经-中金所-上证50指数期权实时行情
/// 
/// 获取指定合约的T型报价数据，包括看涨和看跌期权的买价、卖价、最新价、持仓量等
/// 
/// # 参数
/// - `symbol`: 合约代码，例如 "ho2511"
/// 
/// # 返回
/// - `SinaCffexSpot`: 包含T型报价的完整数据结构
pub async fn option_cffex_sz50_spot_sina(symbol: &str) -> Result<SinaCffexSpot> {
    fetch_cffex_spot("ho", symbol).await
}

/// 新浪财经-中金所-沪深300指数期权实时行情
pub async fn option_cffex_hs300_spot_sina(symbol: &str) -> Result<SinaCffexSpot> {
    fetch_cffex_spot("mo", symbol).await
}

/// 新浪财经-中金所-中证1000指数期权实时行情
pub async fn option_cffex_zz1000_spot_sina(symbol: &str) -> Result<SinaCffexSpot> {
    fetch_cffex_spot("io", symbol).await
}

/// 新浪财经-中金所-上证50指数期权日频数据
/// 
/// 获取指定合约的历史日线数据
/// 
/// # 参数
/// - `symbol`: 合约代码，例如 "ho2511"
/// 
/// # 返回
/// - `Vec<SinaCffexDaily>`: 包含日期、开盘价、最高价、最低价、收盘价、成交量等字段
pub async fn option_cffex_sz50_daily_sina(symbol: &str) -> Result<Vec<SinaCffexDaily>> {
    fetch_cffex_daily("ho", symbol).await
}

/// 中金所-沪深300指数-日频数据
pub async fn option_cffex_hs300_daily_sina(symbol: &str) -> Result<Vec<SinaCffexDaily>> {
    fetch_cffex_daily("mo", symbol).await
}

/// 中金所-中证1000指数-日频数据
pub async fn option_cffex_zz1000_daily_sina(symbol: &str) -> Result<Vec<SinaCffexDaily>> {
    fetch_cffex_daily("io", symbol).await
}

// ============ 内部辅助函数 ============

async fn fetch_cffex_list(product: &str) -> Result<Vec<String>> {
    let url = format!("https://stock.finance.sina.com.cn/futures/view/optionsCffexDP.php/{}/cffex", product);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    // 简单的 HTML 解析：查找 option_suffix 中的 data-value 属性
    let mut contracts = Vec::new();
    
    // 查找 id="option_suffix" 后的内容
    if let Some(suffix_start) = text.find(r#"id="option_suffix""#) {
        let remaining = &text[suffix_start..];
        
        // 提取所有 data-value 属性
        let mut pos = 0;
        while let Some(data_start) = remaining[pos..].find(r#"data-value=""#) {
            let data_start = pos + data_start + 12; // 跳过 'data-value="'
            if let Some(quote_end) = remaining[data_start..].find('"') {
                let contract = remaining[data_start..data_start + quote_end].trim().to_string();
                if !contract.is_empty() && contract.len() < 20 && contract.starts_with(product) {
                    contracts.push(contract);
                }
                pos = data_start + quote_end;
            } else {
                break;
            }
            
            // 限制搜索范围，避免解析整个页面
            if pos > 2000 {
                break;
            }
        }
    }
    
    if contracts.is_empty() {
        return Err(anyhow::anyhow!("No contracts found in HTML"));
    }
    
    Ok(contracts)
}

async fn fetch_cffex_spot(product: &str, symbol: &str) -> Result<SinaCffexSpot> {
    let url = "https://stock.finance.sina.com.cn/futures/api/openapi.php/OptionService.getOptionData";
    let client = build_client()?;
    
    let params = [
        ("type", "futures"),
        ("product", product),
        ("exchange", "cffex"),
        ("pinzhong", symbol),
    ];
    
    let resp = client.get(url).query(&params).send().await?;
    let status = resp.status();
    let text = resp.text().await?;
    
    let start = match text.find('{') {
        Some(pos) => pos,
        None => {
            let head: String = text.chars().take(160).collect();
            return Err(anyhow::anyhow!(
                "No JSON in response (status: {}, len: {}, head: {:?})",
                status,
                text.len(),
                head
            ));
        }
    };
    let end = match text.rfind('}') {
        Some(pos) => pos + 1,
        None => {
            let head: String = text.chars().take(160).collect();
            return Err(anyhow::anyhow!(
                "No JSON in response (status: {}, len: {}, head: {:?})",
                status,
                text.len(),
                head
            ));
        }
    };
    let json_text = &text[start..end];
    
    let json: Value = serde_json::from_str(json_text)?;
    
    let call_data = json["result"]["data"]["up"]
        .as_array()
        .ok_or_else(|| anyhow::anyhow!("No call data"))?;
    
    let put_data = json["result"]["data"]["down"]
        .as_array()
        .ok_or_else(|| anyhow::anyhow!("No put data"))?;
    
    let mut contracts = Vec::new();
    
    for (call, put) in call_data.iter().zip(put_data.iter()) {
        if let (Some(call_arr), Some(put_arr)) = (call.as_array(), put.as_array()) {
            if call_arr.len() >= 9 && put_arr.len() >= 8 {
                contracts.push(SinaCffexContract {
                    call_bid_volume: call_arr[0].as_f64(),
                    call_bid_price: call_arr[1].as_f64(),
                    call_last: call_arr[2].as_f64(),
                    call_ask_price: call_arr[3].as_f64(),
                    call_ask_volume: call_arr[4].as_f64(),
                    call_open_interest: call_arr[5].as_f64(),
                    call_change: call_arr[6].as_f64(),
                    strike: call_arr[7].as_f64(),
                    call_symbol: call_arr[8].as_str().unwrap_or("").to_string(),
                    put_bid_volume: put_arr[0].as_f64(),
                    put_bid_price: put_arr[1].as_f64(),
                    put_last: put_arr[2].as_f64(),
                    put_ask_price: put_arr[3].as_f64(),
                    put_ask_volume: put_arr[4].as_f64(),
                    put_open_interest: put_arr[5].as_f64(),
                    put_change: put_arr[6].as_f64(),
                    put_symbol: put_arr[7].as_str().unwrap_or("").to_string(),
                });
            }
        }
    }
    
    Ok(SinaCffexSpot {
        symbol: symbol.to_string(),
        contracts,
    })
}

async fn fetch_cffex_daily(product: &str, symbol: &str) -> Result<Vec<SinaCffexDaily>> {
    let url = format!("https://stock.finance.sina.com.cn/futures/api/jsonp.php/var%20_{}_{}=/OptionDaylineService.getOptionDayline", product, symbol);
    let client = build_client()?;
    
    let params = [
        ("symbol", symbol),
    ];
    
    let resp = client.get(&url).query(&params).send().await?;
    let text = resp.text().await?;
    
    // 提取 JSON 部分 (JSONP 格式)
    let start = text.find('[').ok_or_else(|| anyhow::anyhow!("No JSON array in response"))?;
    let end = text.rfind(']').ok_or_else(|| anyhow::anyhow!("No JSON array in response"))? + 1;
    let json_text = &text[start..end];
    
    let json: Value = serde_json::from_str(json_text)?;
    let data_list = json.as_array().ok_or_else(|| anyhow::anyhow!("Expected array"))?;
    
    let mut result = Vec::new();
    for item in data_list {
        if let Some(arr) = item.as_array() {
            if arr.len() >= 6 {
                result.push(SinaCffexDaily {
                    date: arr[0].as_str().unwrap_or("").to_string(),
                    open: arr[1].as_f64(),
                    high: arr[2].as_f64(),
                    low: arr[3].as_f64(),
                    close: arr[4].as_f64(),
                    volume: arr[5].as_f64(),
                });
            }
        }
    }
    
    Ok(result)
}

// ============ 上交所扩展接口 ============

/// 新浪财经-上交所-期权合约到期月份列表
/// 
/// 获取上交所期权的所有到期月份
/// 
/// # 参数
/// - `symbol`: 标的代码，如 "50ETF" 或 "300ETF"
/// 
/// # 返回
/// - `Vec<String>`: 到期月份列表，格式如 ["202511", "202512", "202603"]
pub async fn option_sse_list_sina(symbol: &str) -> Result<Vec<String>> {
    let url = "https://stock.finance.sina.com.cn/futures/api/openapi.php/StockOptionService.getStockName";
    let client = build_client()?;
    
    let params = [("exchange", "null"), ("cate", symbol)];
    let resp = client.get(url).query(&params).send().await?;
    let json: Value = resp.json().await?;
    
    let mut months = Vec::new();
    if let Some(arr) = json["result"]["data"]["contractMonth"].as_array() {
        for item in arr.iter().skip(1) {  // 跳过第一个元素
            if let Some(date_str) = item.as_str() {
                // 将 "2025-11" 转换为 "202511"
                let month = date_str.replace("-", "");
                months.push(month);
            }
        }
    }
    
    Ok(months)
}

/// 新浪财经-上交所-期权到期日和剩余天数
/// 
/// 获取指定到期月份的到期日和剩余天数
/// 
/// # 参数
/// - `trade_date`: 到期月份，格式如 "202511"
/// - `symbol`: 标的代码，如 "50ETF" 或 "300ETF"
/// 
/// # 返回
/// - `(String, i32)`: (到期日, 剩余天数)，如 ("2025-11-26", 28)
pub async fn option_sse_expire_day_sina(trade_date: &str, symbol: &str) -> Result<(String, i32)> {
    let url = "https://stock.finance.sina.com.cn/futures/api/openapi.php/StockOptionService.getRemainderDay";
    let client = build_client()?;
    
    // 格式化日期: "202511" -> "2025-11"
    let formatted_date = if trade_date.len() >= 6 {
        format!("{}-{}", &trade_date[..4], &trade_date[4..])
    } else {
        trade_date.to_string()
    };
    
    let params = [
        ("exchange", "null"),
        ("cate", symbol),
        ("date", &formatted_date),
    ];
    
    let resp = client.get(url).query(&params).send().await?;
    let json: Value = resp.json().await?;
    
    let data = &json["result"]["data"];
    let expire_day = data["expireDay"].as_str().unwrap_or("").to_string();
    let remainder_days = data["remainderDays"].as_str()
        .and_then(|s| s.parse::<i32>().ok())
        .unwrap_or(0);
    
    // 如果剩余天数为负，尝试使用XD前缀
    if remainder_days < 0 {
        let xd_symbol = format!("XD{}", symbol);
        let params = [
            ("exchange", "null"),
            ("cate", xd_symbol.as_str()),
            ("date", &formatted_date),
        ];
        
        let resp = client.get(url).query(&params).send().await?;
        let json: Value = resp.json().await?;
        let data = &json["result"]["data"];
        
        let expire_day = data["expireDay"].as_str().unwrap_or("").to_string();
        let remainder_days = data["remainderDays"].as_str()
            .and_then(|s| s.parse::<i32>().ok())
            .unwrap_or(0);
        
        return Ok((expire_day, remainder_days));
    }
    
    Ok((expire_day, remainder_days))
}

/// 新浪财经-上交所-期权合约代码列表
/// 
/// 获取指定到期月份的看涨或看跌期权合约代码
/// 
/// # 参数
/// - `symbol`: 期权类型，"看涨期权" 或 "看跌期权"
/// - `trade_date`: 到期月份，格式如 "202511"
/// - `underlying`: 标的代码，如 "510050" (华夏上证50ETF) 或 "510300" (华泰柏瑞沪深300ETF)
/// 
/// # 返回
/// - `Vec<(usize, String)>`: [(序号, 期权代码)] 列表
pub async fn option_sse_codes_sina(symbol: &str, trade_date: &str, underlying: &str) -> Result<Vec<(usize, String)>> {
    let prefix = if symbol == "看涨期权" { "OP_UP_" } else { "OP_DOWN_" };
    let suffix = if trade_date.len() >= 4 {
        &trade_date[trade_date.len()-4..]
    } else {
        trade_date
    };
    let url = format!("https://hq.sinajs.cn/list={}{}{}", prefix, underlying, suffix);
    
    let client = build_client()?;
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    // 解析格式: var hq_str_OP_UP_5100501511="CON_OP_10004355,CON_OP_10004356,..."
    let start = text.find('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let end = text.rfind('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let data_str = &text[start + 1..end];
    
    let mut codes = Vec::new();
    for (idx, item) in data_str.split(',').enumerate() {
        if item.starts_with("CON_OP_") {
            let code = item[7..].to_string();  // 移除 "CON_OP_" 前缀
            codes.push((idx + 1, code));
        }
    }
    
    Ok(codes)
}

/// 新浪财经-上交所-期权实时价格
/// 
/// 获取指定合约的实时行情数据
/// 
/// # 参数
/// - `contract_code`: 合约代码，例如 "10004355"
/// 
/// # 返回
/// - `SseSpotPrice`: 实时价格数据，包含最新价、涨跌幅、成交量、持仓量等
pub async fn option_sse_spot_price_sina(contract_code: &str) -> Result<SseSpotPrice> {
    let url = format!("https://hq.sinajs.cn/list=CON_OP_{}", contract_code);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    // 解析新浪行情数据格式: var hq_str_CON_OP_10004355="0.1234,1.23,..."
    let start = text.find('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let end = text.rfind('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let data_str = &text[start + 1..end];
    let fields: Vec<&str> = data_str.split(',').collect();
    
    if fields.len() < 43 {
        return Err(anyhow::anyhow!("Insufficient data fields"));
    }
    
    Ok(SseSpotPrice {
        contract_code: contract_code.to_string(),
        // 依据 Python 脚本数据映射：
        // 2: 最新价, 6: 涨幅, 5: 持仓量, 41: 成交量
        last: fields.get(2).and_then(|s| s.parse().ok()),
        change_pct: fields.get(6).and_then(|s| s.parse().ok()),
        volume: fields.get(41).and_then(|s| s.parse().ok()),
        open_interest: fields.get(5).and_then(|s| s.parse().ok()),
    })
}

/// 新浪财经-上交所-标的实时价格
/// 
/// 获取期权标的证券的实时价格
/// 
/// # 参数
/// - `underlying_code`: 标的代码，例如 "510050"
/// 
/// # 返回
/// - `f64`: 标的最新价
pub async fn option_sse_underlying_spot_price_sina(underlying_code: &str) -> Result<f64> {
    let url = format!("https://hq.sinajs.cn/list={}", underlying_code);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    let start = text.find('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let end = text.rfind('"').ok_or_else(|| anyhow::anyhow!("No data in response"))?;
    let data_str = &text[start + 1..end];
    let fields: Vec<&str> = data_str.split(',').collect();
    
    fields.get(3)
        .and_then(|s| s.parse().ok())
        .ok_or_else(|| anyhow::anyhow!("Failed to parse price"))
}

/// 新浪财经-上交所-期权Greeks指标
/// 
/// 获取指定合约的Greeks指标数据
/// 
/// # 参数
/// - `contract_code`: 合约代码
/// 
/// # 返回
/// - `SseGreeks`: Greeks指标，包含Delta、Gamma、Vega、Theta、Rho
pub async fn option_sse_greeks_sina(contract_code: &str) -> Result<SseGreeks> {
    let url = format!("https://hq.sinajs.cn/list=CON_SO_{}", contract_code);
    let client = crate::client::http::build_client_with_headers(vec![
        ("Referer", "https://vip.stock.finance.sina.com.cn/"),
        ("Accept", "*/*"),
        ("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"),
        (
            "User-Agent",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
        ),
        ("Cache-Control", "no-cache"),
        ("Pragma", "no-cache"),
    ])?;

    let resp = client.get(&url).send().await?;
    let status = resp.status();
    let text = resp.text().await?;

    let start = match text.find('"') {
        Some(pos) => pos + 1,
        None => {
            let head: String = text.chars().take(160).collect();
            return Err(anyhow::anyhow!(
                "No CSV in response (status: {}, len: {}, head: {:?})",
                status,
                text.len(),
                head
            ));
        }
    };
    let end = match text.rfind('"') {
        Some(pos) if pos > start => pos,
        _ => {
            let head: String = text.chars().take(160).collect();
            return Err(anyhow::anyhow!(
                "No CSV in response (status: {}, len: {}, head: {:?})",
                status,
                text.len(),
                head
            ));
        }
    };
    let data_str = &text[start..end];
    let parts: Vec<&str> = data_str.split(',').collect();

    let parse_f64 = |idx: usize| -> Option<f64> {
        parts.get(idx).and_then(|s| s.parse::<f64>().ok())
    };

    Ok(SseGreeks {
        contract_code: contract_code.to_string(),
        // Python版本的字段顺序：名称, 成交量, Delta, Gamma, Theta, Vega, 隐含波动率, 最高价, 最低价, 交易代码, 行权价, 最新价, 理论价值
        // 其中 Delta/Gamma/Theta/Vega 位于索引 5..=8；Rho在该源中未提供
        delta: parse_f64(5),
        gamma: parse_f64(6),
        theta: parse_f64(7),
        vega: parse_f64(8),
        rho: None,
        contract_name: parts.get(0).unwrap_or(&"").to_string(),
        volume: parse_f64(4),
        implied_volatility: parse_f64(9),
        high: parse_f64(10),
        low: parse_f64(11),
        trade_code: parts.get(12).unwrap_or(&"").to_string(),
        strike: parse_f64(13),
        last: parse_f64(14),
        theoretical_value: parse_f64(15),
    })
}

/// 新浪财经-上交所-期权分时数据
/// 
/// 获取指定合约的分钟级行情数据
/// 
/// # 参数
/// - `contract_code`: 合约代码
/// 
/// # 返回
/// - `Vec<SseMinute>`: 分时数据列表
pub async fn option_sse_minute_sina(contract_code: &str) -> Result<Vec<SseMinute>> {
    let url = "https://stock.finance.sina.com.cn/futures/api/openapi.php/StockOptionDaylineService.getOptionMinline";
    let client = crate::client::http::build_client_with_headers(vec![
        ("Referer", "https://stock.finance.sina.com.cn/option/quotes.html"),
        ("Accept", "*/*"),
        ("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"),
        ("Cache-Control", "no-cache"),
        ("Pragma", "no-cache"),
        (
            "User-Agent",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
        ),
    ])?;

    let resp = client
        .get(url)
        .query(&[("symbol", format!("CON_OP_{}", contract_code))])
        .send()
        .await?;

    let json: Value = resp.json().await?;
 

    let parse_num = |v: &Value| -> Option<f64> {
        v.as_f64().or_else(|| v.as_str().and_then(|s| {
            let s = s.trim();
            if s.is_empty() || s == "-" { None } else { s.parse::<f64>().ok() }
        }))
    };

    let mut out = Vec::new();
    if let Some(arr) = json.get("result").and_then(|v| v.get("data")).and_then(|v| v.as_array()) {
        let mut last_date: Option<String> = None;
        for item in arr {
            match item {
                Value::Array(row) => {
                    // 索引顺序与 Python 重命名后列一致: [时间, 价格, 成交, 持仓, 均价, 日期]
                    let mut time = row.get(0).and_then(|v| v.as_str()).unwrap_or("").to_string();
                    if let Some(date_str) = row.get(5).and_then(|v| v.as_str()) {
                        if !date_str.is_empty() { last_date = Some(date_str.to_string()); }
                    }
                    if let Some(d) = &last_date { time = format!("{} {}", d, time); }
                    let price = row.get(1).and_then(parse_num);
                    let volume = row.get(2).and_then(parse_num);
                    out.push(SseMinute { time, price, volume });
                }
                Value::Object(obj) => {
                    // 紧凑键映射: i->时间, p->价格, v->成交；可带 d/date/日期
                    let mut time = obj.get("i")
                        .or_else(|| obj.get("time"))
                        .or_else(|| obj.get("min_time"))
                        .or_else(|| obj.get("时间"))
                        .and_then(|v| v.as_str()).unwrap_or("").to_string();
                    if let Some(date_val) = obj.get("d").or_else(|| obj.get("date")).or_else(|| obj.get("日期")) {
                        if let Some(date_str) = date_val.as_str() {
                            if !date_str.is_empty() { last_date = Some(date_str.to_string()); }
                        }
                    }
                    if let Some(d) = &last_date { time = format!("{} {}", d, time); }
                    let price = obj.get("p").and_then(parse_num)
                        .or_else(|| obj.get("price").and_then(parse_num))
                        .or_else(|| obj.get("价格").and_then(parse_num));
                    let volume = obj.get("v").and_then(parse_num)
                        .or_else(|| obj.get("volume").and_then(parse_num))
                        .or_else(|| obj.get("成交").and_then(parse_num));
                    out.push(SseMinute { time, price, volume });
                }
                _ => {}
            }
        }
    } else {
        return Err(anyhow::anyhow!("No JSON array in response"));
    }

    Ok(out)
}

/// 新浪财经-上交所-期权日线数据
/// 
/// 获取指定合约的历史日线数据
/// 
/// # 参数
/// - `contract_code`: 合约代码
/// 
/// # 返回
/// - `Vec<SseDaily>`: 日线数据列表，包含OHLCV和持仓量
pub async fn option_sse_daily_sina(contract_code: &str) -> Result<Vec<SseDaily>> {
    // 对齐 Python(AkShare)实现: 使用 JSONP 接口并添加必要的 headers
    let url = "https://stock.finance.sina.com.cn/futures/api/jsonp_v2.php//StockOptionDaylineService.getSymbolInfo";
    let client = crate::client::http::build_client_with_headers(vec![
        ("Referer", "https://stock.finance.sina.com.cn/option/quotes.html"),
        ("Accept", "*/*"),
        ("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8"),
        ("Cache-Control", "no-cache"),
        ("Pragma", "no-cache"),
        (
            "User-Agent",
            "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.71 Safari/537.36",
        ),
    ])?;

    let resp = client
        .get(url)
        .query(&[("symbol", format!("CON_OP_{}", contract_code))])
        .send()
        .await?;
    let text = resp.text().await?;
  

    // JSONP: 优先按 (...) 截取；若失败再回退到 [ ... ]
    let (start, end) = if let (Some(s), Some(e)) = (text.find('('), text.rfind(')')) {
        (s + 1, e)
    } else if let (Some(s), Some(e)) = (text.find('['), text.rfind(']')) {
        (s, e + 1)
    } else {
        let head: String = text.chars().take(160).collect();
        return Err(anyhow::anyhow!(
            "No JSON array in response (len: {}, head: {:?})",
            text.len(), head
        ));
    };
    let json_text = &text[start..end];
    let json: Value = serde_json::from_str(json_text)?;

    let parse_num = |v: &Value| -> Option<f64> {
        v.as_f64().or_else(|| v.as_str().and_then(|s| {
            let s = s.trim();
            if s.is_empty() || s == "-" { None } else { s.parse::<f64>().ok() }
        }))
    };

    let mut result = Vec::new();
    if let Some(arr) = json.as_array() {
        for item in arr {
            match item {
                // 数组形式: [日期, 开盘, 最高, 最低, 收盘, 成交量]
                Value::Array(row) => {
                    let get = |i: usize| row.get(i).unwrap_or(&Value::Null);
                    result.push(SseDaily {
                        date: get(0).as_str().unwrap_or("").to_string(),
                        open: parse_num(get(1)),
                        high: parse_num(get(2)),
                        low: parse_num(get(3)),
                        close: parse_num(get(4)),
                        volume: parse_num(get(5)),
                        open_interest: None,
                    });
                }
                // 对象形式: 兼容英文字段名与紧凑键(d/o/h/l/c/v/oi)
                Value::Object(obj) => {
                    let gvs = |ks: &[&str]| -> &Value {
                        for &k in ks { if let Some(v) = obj.get(k) { return v; } }
                        &Value::Null
                    };
                    result.push(SseDaily {
                        date: gvs(&["d", "date"]).as_str().unwrap_or("").to_string(),
                        open: parse_num(gvs(&["o", "open"])),
                        high: parse_num(gvs(&["h", "high"])),
                        low: parse_num(gvs(&["l", "low"])),
                        close: parse_num(gvs(&["c", "close"])),
                        volume: parse_num(gvs(&["v", "volume"])),
                        open_interest: obj.get("oi").and_then(parse_num)
                            .or_else(|| obj.get("open_interest").and_then(parse_num)),
                    });
                }
                _ => {}
            }
        }
    } else {
        return Err(anyhow::anyhow!("Expected array"));
    }

    Ok(result)
}

// 已移除精简版分钟数据函数（返回 SseMinute），请使用完整字段版本。

// ============ 商品期权接口 ============

/// 新浪财经-商品期权-合约信息
/// 
/// 获取指定商品期权的合约信息
/// 
/// # 参数
/// - `symbol`: 期权代码，例如 "cu2501"
/// 
/// # 返回
/// - `Vec<CommodityContract>`: 合约信息列表
pub async fn option_commodity_contract_sina(symbol: &str) -> Result<Vec<CommodityContract>> {
    let url = format!("https://stock.finance.sina.com.cn/futures/api/openapi.php/OptionService.getOptionData?type=commodity&product={}", symbol);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    let start = text.find('{').ok_or_else(|| anyhow::anyhow!("No JSON in response"))?;
    let end = text.rfind('}').ok_or_else(|| anyhow::anyhow!("No JSON in response"))? + 1;
    let json_text = &text[start..end];
    let json: Value = serde_json::from_str(json_text)?;
    
    let mut contracts = Vec::new();
    if let Some(data) = json["result"]["data"].as_object() {
        for (code, info) in data {
            if let Some(info_obj) = info.as_object() {
                contracts.push(CommodityContract {
                    contract_code: code.clone(),
                    contract_name: info_obj.get("name").and_then(|v| v.as_str()).unwrap_or("").to_string(),
                    underlying_code: info_obj.get("underlying").and_then(|v| v.as_str()).unwrap_or("").to_string(),
                    option_type: info_obj.get("type").and_then(|v| v.as_str()).unwrap_or("").to_string(),
                    strike: info_obj.get("strike").and_then(|v| v.as_f64()),
                });
            }
        }
    }
    
    Ok(contracts)
}

/// 新浪财经-商品期权-T型报价表
/// 
/// 获取指定商品期权的T型报价数据
/// 
/// # 参数
/// - `symbol`: 期权代码
/// 
/// # 返回
/// - `Vec<CommodityContractTable>`: T型报价数据列表
pub async fn option_commodity_contract_table_sina(symbol: &str) -> Result<Vec<CommodityContractTable>> {
    let url = format!("https://stock.finance.sina.com.cn/futures/api/openapi.php/OptionService.getOptionData?type=commodity&product={}", symbol);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    let start = text.find('{').ok_or_else(|| anyhow::anyhow!("No JSON in response"))?;
    let end = text.rfind('}').ok_or_else(|| anyhow::anyhow!("No JSON in response"))? + 1;
    let json_text = &text[start..end];
    let json: Value = serde_json::from_str(json_text)?;
    
    let call_data = json["result"]["data"]["up"]
        .as_array()
        .ok_or_else(|| anyhow::anyhow!("No call data"))?;
    
    let put_data = json["result"]["data"]["down"]
        .as_array()
        .ok_or_else(|| anyhow::anyhow!("No put data"))?;
    
    let mut result = Vec::new();
    for (call, put) in call_data.iter().zip(put_data.iter()) {
        if let (Some(call_arr), Some(put_arr)) = (call.as_array(), put.as_array()) {
            if call_arr.len() >= 9 && put_arr.len() >= 8 {
                result.push(CommodityContractTable {
                    call_code: call_arr[8].as_str().unwrap_or("").to_string(),
                    call_last: call_arr[2].as_f64(),
                    call_change: call_arr[6].as_f64(),
                    strike: call_arr[7].as_f64(),
                    put_code: put_arr[7].as_str().unwrap_or("").to_string(),
                    put_last: put_arr[2].as_f64(),
                    put_change: put_arr[6].as_f64(),
                });
            }
        }
    }
    
    Ok(result)
}

/// 新浪财经-商品期权-历史数据
/// 
/// 获取指定商品期权合约的历史行情数据
/// 
/// # 参数
/// - `symbol`: 合约代码
/// 
/// # 返回
/// - `Vec<CommodityOptionHist>`: 历史数据列表
pub async fn option_commodity_hist_sina(symbol: &str) -> Result<Vec<CommodityOptionHist>> {
    let url = format!("https://stock.finance.sina.com.cn/futures/api/jsonp.php/var%20_{}=/OptionDaylineService.getOptionDayline?symbol={}", symbol, symbol);
    let client = build_client()?;
    
    let resp = client.get(&url).send().await?;
    let text = resp.text().await?;
    
    let start = text.find('[').ok_or_else(|| anyhow::anyhow!("No JSON array in response"))?;
    let end = text.rfind(']').ok_or_else(|| anyhow::anyhow!("No JSON array in response"))? + 1;
    let json_text = &text[start..end];
    let json: Value = serde_json::from_str(json_text)?;
    
    let mut result = Vec::new();
    if let Some(arr) = json.as_array() {
        for item in arr {
            if let Some(item_arr) = item.as_array() {
                if item_arr.len() >= 6 {
                    result.push(CommodityOptionHist {
                        date: item_arr[0].as_str().unwrap_or("").to_string(),
                        open: item_arr[1].as_f64(),
                        high: item_arr[2].as_f64(),
                        low: item_arr[3].as_f64(),
                        close: item_arr[4].as_f64(),
                        volume: item_arr[5].as_f64(),
                    });
                }
            }
        }
    }
    
    Ok(result)
}
